#!/usr/bin/python2.6

'''Some global functions and constants for Voogle'''

from optionClass import *
import pyttsx
import time
import re

RESMAX = 32 #The maximum number of results provided by the Google API


def cleanHTML(html):
    '''Cleans up HTML for human aural consumption: takes out tags, and repalces &# codes and % codes with actual characters.'''

    html = html.replace('&amp;', '&')
    html = html.replace('&lt;', '<')
    html = html.replace('&gt;', '>')
    htmlCodeRE = re.compile(r"&#(\d+);")
    html = regexReplace(html, htmlCodeRE, 1, lambda x: chr(int(x)))
    htmlTagRE = re.compile(r'<.*?>', flags = re.S)
    html = regexReplace(html, htmlTagRE, 0, lambda x: '')
    urlHexRE = re.compile(r'%([0-9a-f]{2})', re.I)
    html = regexReplace(html, urlHexRE, 1, lambda x: chr(int(x, 16)))
    
    return html

def regexReplace(text, regexIN, groupnum, repfunc):
    '''Searches for patterns matching the regex in the text string, takes group groupnum out of the match and feeds it into the function repfunc.  Then replaces the entire regex with the result of repfunc.  Repfunc takes and returns a string.'''
    while True:
        match = re.search(regexIN, text)
        
        if not match:
            break

        group = match.group(groupnum)
        wholeMatch = match.group(0)
        repstr = repfunc(group)

        text = text.replace(wholeMatch, repstr)

    return text

def out(output, options = {'speech' : 'off'}):
    '''A dummy function for user output.  Once we integrate with the voice API this function will also say what it's printing.'''
    
    print output

    if options.get('speech', None) == 'on':
        
        engine = pyttsx.init()
        engine.setProperty('voice', 'english-us')

        if engine.getProperty('rate') != options.get('rate', 200):
            engine.setProperty('rate', options.get('rate', 200))

        if engine.getProperty('volume') != options.get('volume', 100)/100.:
            engine.setProperty('volume', options.get('volume', 100)/100.)

        engine.say(output)
        engine.runAndWait()



def getInput(prompt = None, **kwargs):
    '''A dummy function for user input.  Once we integrate with the voice API this function will take voice or keyboard input.'''

    return raw_input(prompt if prompt != None else '% ').strip()

def getLowerInput(prompt = None, **kwargs):
    '''Get lowercased input'''
    return getInput(prompt).lower()

# Build up default options object

defaultOptVals = {'input' : 'keyboard', 
                  'url' : 'short', 
                  'results' : 10, 
                  'lucky' : 'false',
                  'speech' : 'on',
                  'rate' : 200,
                  'volume' : 100}

possibleOptVals = {'input' : ['keyboard', 'voice'],
                   'url' : ['full', 'short'],
                   'results' : range(1, RESMAX + 1),
                   'lucky' : ['true', 'false'],
                   'speech' : ['on', 'off'],
                   'rate' : range(100, 401),
                   'volume' : range(101)}

optTypes = {'input' : str,
            'url' : str,
            'results' : int,
            'lucky' : str,
            'speech' : str,
            'rate' : int,
            'volume' : int}

optPrompts = {'input' : 'Take input from the keyboard or the' +\
                  'microphone using voice recognition',
              'url' : 'Show full search result URLs or just ' +\
                  "the domain name.",
              'results' : "How many results to show, between 1 " + \
                  'and' + str(RESMAX),
              'lucky' : "Do you feel lucky?",
              'speech' : 'Turn audio output on or off',
              'rate' : "How fast text is read, in words per minute.  " + \
                  "Between 100 and 400.",
              'volume' : "How loud text is read.  Between 0 and 100."}

defaultOptions = optionClass(getLowerInput,
                             out,
                             defaults = defaultOptVals, 
                             possible = possibleOptVals, 
                             types = optTypes,
                             prompts = optPrompts)

def main():
    o = optionClass(infunc = raw_input,
                    outfunc = out,
                    optionVals = {'speech' : 'on','rate' : 200,'volume' : 100},
                    defaults = {'speech' : 'off', 'rate' : 200,'volume' : 100},
                    types = {'speech':str,'rate':int,'volume':int})
    o.optionMenu()


if __name__ == '__main__':
    main()
